/****************************************************************************
   Copyright 2013 Stacy Doss

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
****************************************************************************/

%{

#include <stdarg.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <vector>

#include "DefParser.h"
#include "Def.h"
#define __YYSTYPE std::string

int yydebug = 1;
int indent  = 0;

//extern "C" int yylex();
extern "C" int yyparse();
extern "C" FILE *yyin;

using util::Point;


static void yyerror (const char *msg);
int yylex (void);

def::Component* component;
def::Pin* 		pin;
def::Net* 		net;

%}


%union {
    int							i;
    float						f;
    char*						s;
    bool						b;
    std::vector<std::string>*	vs;
    util::Point*				pt;
}

%token <s> NAME
%token <i> INT
%token <f> FLOAT
%token <s> QSTRING

%token <s> RIGHTBRACKET
%token <s> RIGHTBRACE
%token <s> RIGHTPAREN
%token <s> RIGHTANGLE
%token <s> LEFTBRACKET
%token <s> LEFTBRACE
%token <s> LEFTPAREN
%token <s> LEFTANGLE

%token <s> COLON
%token <s> BACKSLASH
%token <s> PERIOD
%token <s> PIPE
%token SEMI
%token COMMA
%token QUOTE
%token MINUS
%token PLUS

%token VERSION
%token NAMESCASESENSITIVE
%token BUSBITCHARS
%token DIVIDERCHAR
%token DESIGN
%token TECHNOLOGY
%token UNITS
%token HISTORY
%token PROPERTYDEFINITIONS
%token DIEAREA
%token ROWS
%token TRACKS
%token GCELLGRID
%token VIAS
%token REGIONS
%token COMPONENTS
%token PINS
%token PINPROPERTIES
%token BLOCKAGES
%token SLOTS
%token FILLS
%token SPECIALNETS
%token NETS
%token SCANCHAINS
%token GROUPS
%token BEGINEXT
%token END

%token ON
%token OFF

%token DISTANCE
%token MICRONS

%token X
%token Y
%token DO
%token STEP
%token LAYER

%token EEQMASTER
%token SOURCE
%token NETLIST
%token DIST
%token USER
%token TIMING
%token FOREIGN
%token FIXED
%token COVER
%token PLACED
%token UNPLACED
%token WEIGHT
%token REGION
%token PROPERTY
%token N
%token S
%token E
%token W
%token FN
%token FS
%token FE
%token FW
%token ONE
%token ZERO

%token NET
%token SPECIAL
%token DIRECTION
%token USE
%token INPUT
%token OUTPUT
%token INOUT
%token FEEDTHRU
%token SIGNAL
%token POWER
%token GROUND
%token CLOCK
%token TIEOFF
%token ANALOG
%token SCAN
%token RESET
%token ANTENNAPINPARTIALMETALAREA
%token ANTENNAPINPARTIALMETALSIDEAREA
%token ANTENNAPINPARTIALCUTAREA
%token ANTENNAPINDIFFAREA
%token ANTENNAMODEL
%token OXIDE1
%token OXIDE2
%token OXIDE3
%token OXIDE4
%token ANTENNAPINGATEAREA
%token ANTENNAPINMAXAREACAR
%token ANTENNAPINMAXSIDEAREACAR
%token ANTENNAPINMAXCUTCAR

%token COMPONENT
%token PLACEMENT
%token PUSHDOWN
%token RECT

%token TYPE
%token FENCE
%token PATTERNNAME
%token GUIDE
%token BY

%token PIN
%token SYNTHESIZED
%token MUSTJOIN
%token SHIELDNET

%token NEW
%token STAR
%token TAPER	
%token TAPERRULE
%token NOSHIELD
%token ROUTED
%token RING
%token PADRING
%token BLOCKRING
%token STRIPE
%token FOLLOWPIN
%token IOWIRE
%token COREWIRE
%token BLOCKWIRE
%token BLOCKAGEWIRE
%token FILLWIRE
%token DRCFILL
%token SHAPE
%token SHIELD

%token VOLTAGE
%token FIXEDBUMP
%token ORIGINAL
%token PATTERN
%token BALANCED
%token STEINER
%token TRUNK
%token WIREDLOGIC
%token ESTCAP

%token VPIN
%token SUBNET
%token XTALK 
%token NONDEFAULTRULE 
%token FREQUENCY

%token COMMONSCANPINS
%token PARTITION
%token MAXBITS
%token FLOATING
%token ORDERED
%token IN
%token OUT
%token BITS
%token START
%token STOP

%token INTEGER
%token REAL
%token STRING
%token COMPONENTPIN
%token SPECIALNET
%token GROUP
%token RANGE
%token ROW

%token <s> VERSIONSTRING
%token <s> DELIM
%token <s> LEFTDELIM
%token <s> RIGHTDELIM
%token <s> RAWTEXT

%type <s>	name
%type <b>	on_off
%type <s>	delim 
%type <s>	leftdelim 
%type <s>	rightdelim 
%type <pt>	point
%type <s>	x_or_y
%type <vs>	track_layers
%type <s>	orient
%type <b>	synthesized


%% /* Grammar rules and actions follow */
def_definition:
				version
				namescasesensitive
				dividerchar
				busbitchars
				design
				technology
				units
				history
				propertydefinitions
				diearea
				rows
				tracks
				gcellgrids
				vias
				regions
				components
				pins
				pinproperties
				blockages
				slots
				fills
				specialnets
				nets
				scanchains
				groups
//				beginext
				end;

version:
				VERSION VERSIONSTRING SEMI { root->addAttribute("version", $2) };

namescasesensitive:
				NAMESCASESENSITIVE on_off SEMI { root->addAttribute("namescasesensitive", $2) };

on_off:
				ON {$$ = true;} | OFF {$$ = false;};				

dividerchar:
				DIVIDERCHAR QUOTE delim QUOTE SEMI { root->addAttribute("dividerchar", $3) };

delim:
				COLON 		{$$ = $1}
				| BACKSLASH	{$$ = $1}
				| PERIOD	{$$ = $1}
				| PIPE		{$$ = $1};								

busbitchars:
				BUSBITCHARS QUOTE leftdelim rightdelim QUOTE SEMI {
					root->addAttribute("leftbusbitchar", $3);
					root->addAttribute("rightbusbitchar", $4);
				}

leftdelim:
				LEFTBRACE 		{$$ = $1}
				| LEFTBRACKET 	{$$ = $1}
				| LEFTPAREN 	{$$ = $1}
				| LEFTANGLE 	{$$ = $1};

rightdelim:
				RIGHTBRACE		{$$ = $1}
				| RIGHTBRACKET	{$$ = $1}
				| RIGHTPAREN 	{$$ = $1}
				| RIGHTANGLE	{$$ = $1};

design:
				DESIGN name SEMI { root->addAttribute("design", $2); };

technology:
				| TECHNOLOGY name SEMI { root->addAttribute("technology", $2) };

units:
				| UNITS DISTANCE MICRONS INT SEMI { root->addAttribute("units", $4) };

history:
				| HISTORY SEMI;

propertydefinitions:
				|
				PROPERTYDEFINITIONS
				propertydefinitions_list
				END PROPERTYDEFINITIONS
				
propertydefinitions_list:
				propertydefinition
				| propertydefinitions_list propertydefinition

propertydefinition:
				object_type name prop_type range prop_value;

object_type:
				COMPONENT | COMPONENTPIN | DESIGN | GROUP | NET | REGION | ROW | SPECIALNET;
				
prop_type:
				INTEGER | REAL | STRING;

range:
				| RANGE number number;

prop_value:		
				| value;

diearea:
				| DIEAREA point point SEMI { root->setDieArea($2, $3)};

point:
				LEFTPAREN INT INT RIGHTPAREN {$$ = new Point($2, $3);}
				| LEFTPAREN FLOAT FLOAT RIGHTPAREN {$$ = new Point($2, $3);}
				;
												
rows:
				| rows row;

row:
				ROWS name name number number {expect_orient = 1} orient
				row_def
				row_properties SEMI;
				
row_def:
				DO number BY {expect_digit=1} ONE STEP number {expect_digit=1} ZERO 
				| DO {expect_digit=1} ONE BY number STEP {expect_digit=1} ZERO number;

row_properties:
				| row_properties PLUS property;

property:
				PROPERTY name_value_list;

name_value_list:
				| name_value_list name value;
								
tracks:
				| track tracks;

track:
				TRACKS x_or_y INT DO INT STEP INT track_layers SEMI {
					def::Track* track = new def::Track();
					track->setXY($2);
					track->setStart($3);
					track->setCount($5);
					track->setSpace($7);
					track->setLayers($8);
					root->addTrack(track);
				}
				;

x_or_y:
				X	{$$ = (char *)"X"} 
				| Y	{$$ = (char *)"Y"};

track_layers:
				| LAYER name track_layers;
				
gcellgrids:
				| gcellgrid gcellgrids;

gcellgrid:
				GCELLGRID x_or_y INT DO INT STEP INT SEMI {
					def::GCellGrid* gCellGrid = new def::GCellGrid();
					gCellGrid->setXY($2);
					gCellGrid->setStart($3);
					gCellGrid->setCount($5);
					gCellGrid->setSpace($7);
					root->addGCellGrid(gCellGrid);
				}
				;
vias:
				|
				VIAS INT SEMI
				via_list
				END VIAS ;

via_list:
				| via_list via ;

via:
				MINUS name
					via_phrases
					SEMI;			

via_phrases:
				| via_phrases PLUS via_phrase;

via_phrase:
				PATTERNNAME name
				| layer_rects
				
layer_rects:
				RECT name point point
				| layer_rects RECT name point point

regions:
				|
				REGIONS INT SEMI
				region_list
				END REGIONS ;

region_list:
				| region_list region ;

region:
				MINUS name point_list
					region_phrases
					SEMI;			

point_list:
				point
				| point_list point;
				
region_phrases:
				| region_phrases PLUS region_phrase;

region_phrase:
				| TYPE FENCE
				| TYPE GUIDE
				| property;
				
components:
				COMPONENTS INT SEMI
				component_list
				END COMPONENTS ;

component_list:
				| component_list component ;

component:
				MINUS { component = new def::Component() } name name 
					comp_phrases
					SEMI { root->addComponent(component) };

comp_phrases:
				| comp_phrases PLUS comp_phrase;

comp_phrase:
				comp_eeqmaster
				| comp_source
				| comp_foreign
				| comp_placement
				| comp_weight
				| comp_region
				| property;

comp_eeqmaster:
				EEQMASTER name { component->setName($2) };

comp_source:
				SOURCE comp_source_type;

comp_source_type:
				NETLIST		{ component->setSource(util::NETLIST); }
				| DIST		{ component->setSource(util::DIST); }
				| USER		{ component->setSource(util::USER); }
				| TIMING	{ component->setSource(util::TIMING); };

comp_foreign:
				FOREIGN name comp_foreign_pt_orient { component->setForeignName($2) };

comp_foreign_pt_orient:
				point {expect_orient = 1;} orient {
					component->setForeignOrigin($1);
					component->setForeignOrient($3);
				}

orient:
				N		{ $$ = (char *)"N"; }
				| S		{ $$ = (char *)"S"; }
				| E		{ $$ = (char *)"E"; }
				| W		{ $$ = (char *)"W"; }
				| FN	{ $$ = (char *)"FN"; }
				| FS	{ $$ = (char *)"FS"; }
				| FE	{ $$ = (char *)"FE"; }
				| FW	{ $$ = (char *)"FW"; };

comp_placement:
				comp_unplaced
				| comp_placed;
				
comp_unplaced:
				UNPLACED { component->setPlacement(util::UNPLACED); };

comp_placed:
				FIXED comp_pt_orient	{ component->setPlacement(util::FIXED); }
				| COVER comp_pt_orient 	{ component->setPlacement(util::COVER); }
				| PLACED comp_pt_orient	{ component->setPlacement(util::PLACED); };

comp_pt_orient:
				point {expect_orient = 1;} orient {
					component->setOrigin($1);
					component->setOrient($3);
				}

comp_weight:
				WEIGHT INT { component->setWeight($2); };
				
comp_region:	
				REGION name  { component->setRegionName($2); };

pins:
				PINS INT SEMI
				pin_list
				END PINS ;

pin_list:
				| pin_list pin;

pin:
				MINUS name PLUS NET name { pin = new def::Pin($2, $5) }
					pin_phrases
					SEMI { root->addPin(pin); };			

pin_phrases:
				| pin_phrases PLUS pin_phrase;

pin_phrase:
				pin_special
				| pin_direction
				| pin_use
				| pin_antennapinpartialmetalarea
				| pin_antennapinpartialmetalsidearea
				| pin_antennapinpartialcutarea
				| pin_antennapindiffarea
				| pin_antennamodel
				| pin_antennapingatearea
				| pin_antennapinmaxareacar
				| pin_antennapinmaxsideareacar
				| pin_antennapinmaxcutcar
				| pin_layer
				| pin_placement;

pin_special:
				SPECIAL;

pin_direction:
				DIRECTION pin_direction_def;
				
pin_direction_def:
				INPUT		{ pin->setDirection(util::INPUT); } 
				| OUTPUT	{ pin->setDirection(util::OUTPUT); } 
				| INOUT		{ pin->setDirection(util::INOUT); } 
				| FEEDTHRU	{ pin->setDirection(util::FEEDTHRU); } ;
				
pin_use:
				USE pin_use_def ;
				
pin_use_def:
				SIGNAL		{ pin->setUse(util::SIGNAL); }
				| POWER		{ pin->setUse(util::POWER); }
				| GROUND	{ pin->setUse(util::GROUND); }
				| CLOCK		{ pin->setUse(util::CLOCK); }
				| TIEOFF	{ pin->setUse(util::TIEOFF); }
				| ANALOG	{ pin->setUse(util::ANALOG); }
				| SCAN		{ pin->setUse(util::SCAN); }
				| RESET		{ pin->setUse(util::RESET); };

pin_antennapinpartialmetalarea:
				ANTENNAPINPARTIALMETALAREA value_layer_pair;
				
value_layer_pair:
				number
				| number LAYER name;

pin_antennapinpartialmetalsidearea:
				ANTENNAPINPARTIALMETALSIDEAREA value_layer_pair;

pin_antennapinpartialcutarea:
				ANTENNAPINPARTIALCUTAREA  value_layer_pair;

pin_antennapindiffarea:
				ANTENNAPINDIFFAREA value_layer_pair;

pin_antennamodel:
				ANTENNAMODEL pin_antennamodel_def;

pin_antennamodel_def:
				OXIDE1 | OXIDE2 | OXIDE3 | OXIDE4;

pin_antennapingatearea:
				ANTENNAPINGATEAREA value_layer_pair;

pin_antennapinmaxareacar:
				ANTENNAPINMAXAREACAR value_layer_pair;

pin_antennapinmaxsideareacar:
				ANTENNAPINMAXSIDEAREACAR value_layer_pair;

pin_antennapinmaxcutcar:
				ANTENNAPINMAXCUTCAR value_layer_pair;

pin_layer:
				LAYER name point point {pin->setLayer($2, $3, $4)};

pin_placement:
				FIXED pin_pt_orient		{ pin->setPlacement(util::FIXED); }
				| COVER pin_pt_orient 	{ pin->setPlacement(util::COVER); }
				| PLACED pin_pt_orient	{ pin->setPlacement(util::PLACED); };

pin_pt_orient:
				point {expect_orient = 1;} orient {
					pin->setOrigin($1);
					pin->setOrient($3);
				};

pinproperties:
				| 
				PINPROPERTIES INT SEMI
					pinproperty_list
				END PINPROPERTIES;

pinproperty_list:
				| pinproperty_list pinproperty;

pinproperty:
				MINUS name name pinproperty_property_list
				| MINUS PIN name pinproperty_property_list;

pinproperty_property_list:
				| pinproperty_property_list PLUS property;

blockages:
				| 
				BLOCKAGES INT SEMI
				blockage_list
				END BLOCKAGES;

blockage_list:
				| blockage_list blockage;

blockage:
				layer_blockage | placement_blockage;
								
layer_blockage:
				MINUS LAYER name
				layer_blockage_type
				rects;

layer_blockage_type:
				PLUS COMPONENT name
				| PLUS SLOTS 
				| PLUS FILLS
				| PLUS PUSHDOWN;

rects:
				rect
				| rect rects; 

rect:
				RECT point point;
				
placement_blockage:
				MINUS PLACEMENT
				placement_blockage_type
				rects;

placement_blockage_type:
				PLUS COMPONENT name
				| PLUS PUSHDOWN;

slots:
				|
				SLOTS INT SEMI
				slot_list
				END SLOTS

slot_list:
				| slot_list slot;
				
slot:
				MINUS LAYER name rects;

fills:
				|
				FILLS INT SEMI
				fill_list
				END FILLS

fill_list:
				| fill_list fill;
				
fill:
				MINUS LAYER name rects;
				
specialnets:
				|
				SPECIALNETS INT SEMI 
				specialnet_list
				END SPECIALNETS ;

specialnet_list:
				| specialnet_list specialnet;

specialnet:
				MINUS name specialnet_connections
					specialnet_phrases
					SEMI;

specialnet_connections:
				| specialnet_connections specialnet_connection;

specialnet_connection:
				LEFTPAREN name RIGHTPAREN
				| LEFTPAREN name name RIGHTPAREN synthesized;

specialnet_phrases:
				| specialnet_phrases PLUS specialnet_phrase;

specialnet_phrase:
				specialnet_voltage
				| special_wiring
				| specialnet_source
				| specialnet_fixedbump
				| specialnet_original
				| specialnet_use
				| specialnet_pattern
				| specialnet_estcap
				| specialnet_weight
				| property;

specialnet_voltage:
				VOLTAGE number;

specialnet_source:
				SOURCE specialnet_source_type;

specialnet_source_type:
				DIST | NETLIST | TIMING | USER;

specialnet_fixedbump:
				FIXEDBUMP;

specialnet_original:
				ORIGINAL name;

specialnet_use:
				USE specialnet_use_type;

specialnet_use_type:
				ANALOG | CLOCK | GROUND | POWER | RESET | SCAN | SIGNAL | TIEOFF;
				
specialnet_pattern:
				PATTERN specialnet_pattern_type;
				
specialnet_pattern_type:
				BALANCED | STEINER | TRUNK | WIREDLOGIC;

specialnet_estcap:
				ESTCAP number;

specialnet_weight:
				WEIGHT number;

special_wiring:
				special_wiring_type
				name number
				special_wiring_shape
				special_wiring_start
				special_wiring_locations
				special_wiring_additional;
				

special_wiring_type:
				COVER | FIXED | ROUTED | SHIELD name;

special_wiring_shape:
				| SHAPE special_wiring_shape_type;

special_wiring_shape_type:
				RING | PADRING | BLOCKRING | STRIPE | FOLLOWPIN | IOWIRE | COREWIRE | BLOCKWIRE | BLOCKAGEWIRE | FILLWIRE | DRCFILL;

special_wiring_start:
				LEFTPAREN number number RIGHTPAREN;

special_wiring_locations:
				special_wiring_location
				| special_wiring_locations special_wiring_location;
				
special_wiring_location:
				LEFTPAREN STAR number RIGHTPAREN;
				| LEFTPAREN number STAR RIGHTPAREN;
				| name opt_pattern;

opt_pattern:
				| DO number BY number STEP number number;

special_wiring_additional:
				special_wire
				| special_wiring_additional special_wire;

special_wire:
				NEW name number
				special_wiring_shape
				special_wiring_start
				special_wiring_locations;
				

nets:
				NETS INT SEMI
				net_list
				END NETS ;

net_list:
				| net_list net;

net:
				MINUS name { net = new def::Net($2); } net_connections 
					net_phrases
					SEMI { root->addNet(net); };			

net_connections:
				MUSTJOIN LEFTPAREN name name RIGHTPAREN {
					def::ComponentConnection* connect = new def::ComponentConnection($3, $4);
					net->addMustjoin(connect);
				}
				| net_connections2;

net_connections2:
				| net_connections net_connection ;

net_connection:
				LEFTPAREN name name RIGHTPAREN synthesized {
					def::ComponentConnection* connect = new def::ComponentConnection($2, $3);
					net->addConnection(connect);
				}
				| LEFTPAREN PIN name RIGHTPAREN synthesized {
					def::ComponentConnection* connect = new def::ComponentConnection("PIN", $4);
					net->addPrimaryPin(connect);
				};

synthesized:
				{ $$ = false; }
				| SYNTHESIZED { $$ = true; };

net_phrases:
				| net_phrases PLUS net_phrase ;

net_phrase:
				net_shield
				| net_vpin
				| net_subnet
				| net_nondefaultrule
				| regular_wiring
				| net_xtalk
				| net_source
				| net_fixedbump
				| net_frequency
				| net_original
				| net_use
				| net_pattern
				| net_estcap
				| net_weight
				| property;

net_shield:
				SHIELDNET name;

net_vpin:
				VPIN name vpin_layer point point vpin_placement;

vpin_layer:
				| LAYER name;
				
vpin_placement:
				| PLACED point {expect_orient=1} orient 
				| FIXED  point {expect_orient=1} orient
				| COVER  point {expect_orient=1} orient;

net_subnet:
				SUBNET name
				subnet_pin_defs
				NONDEFAULTRULE name
				regular_wiring;

subnet_pin_defs:
				| subnet_pin_defs subnet_pin_def;

subnet_pin_def:
				LEFTPAREN name name RIGHTPAREN
				| LEFTPAREN PIN name RIGHTPAREN
				| LEFTPAREN VPIN name RIGHTPAREN;

net_xtalk:
				XTALK name;

net_nondefaultrule:
				NONDEFAULTRULE name;

net_source:
				SOURCE net_source_type;

net_source_type:
				DIST | NETLIST | TIMING | USER;

net_fixedbump:
				FIXEDBUMP;

net_frequency:
				FREQUENCY number;
				
net_original:
				ORIGINAL name;

net_use:
				USE net_use_type;

net_use_type:
				ANALOG | CLOCK | GROUND | POWER | RESET | SCAN | SIGNAL | TIEOFF;

net_pattern:
				PATTERN net_pattern_type;
				
net_pattern_type:
				BALANCED | STEINER | TRUNK | WIREDLOGIC;

net_estcap:
				ESTCAP number;

net_weight:
				WEIGHT number;

regular_wiring:
				PLUS wiring_type
				wiring_start
				wiring
				wiring_additional
				

wiring_type:
				COVER | FIXED | ROUTED | NOSHIELD;

wiring_start:
				name taper location;

taper:
				| TAPER
				| TAPERRULE name;

location:
				LEFTPAREN number number opt_value RIGHTPAREN;
				
wiring:
				| wiring wire;
				
wire:
				LEFTPAREN number STAR opt_value RIGHTPAREN
				| LEFTPAREN STAR number opt_value RIGHTPAREN
				| LEFTPAREN STAR STAR opt_value RIGHTPAREN
				| name;

opt_value:
				| value;
											
wiring_additional:
				NEW wiring_start wiring
				| wiring_additional NEW wiring_start wiring;
								
scanchains:
				|
				SCANCHAINS INT SEMI
				scanchains_list
				END SCANCHAINS;

scanchains_list:
				| scanchains_list scanchain;

scanchain:
				MINUS name scanchain_phrases SEMI;

scanchain_phrases:
				| scanchain_phrases PLUS scanchain_phrase;

scanchain_phrase:
				PARTITION name max_bits
				| COMMONSCANPINS scanchain_inout_pins
				| START comp_or_pin outpin
				| FLOATING scan_parts
				| ORDERED scan_parts
				| STOP comp_or_pin inpin;

max_bits:
				| MAXBITS INT;
				
scanchain_inout_pins:
				| scanchain_in_pin
				| scanchain_out_pin
				| scanchain_in_pin scanchain_out_pin;				

scanchain_in_pin:
				LEFTPAREN {expect_in_or_out = 1;} IN NAME RIGHTPAREN

scanchain_out_pin:
				LEFTPAREN {expect_in_or_out = 1;} OUT NAME RIGHTPAREN

comp_or_pin:
				name | PIN;
				
outpin:
				| name ;

inpin:
				| name ;

scan_parts:
				| scan_parts scan_part;
				
scan_part:
				name scanchain_inout_pins_bits;
 
scanchain_inout_pins_bits:
				| scanchain_in_pin
				| scanchain_out_pin
				| scanchain_bits
				| scanchain_in_pin scanchain_out_pin				
				| scanchain_in_pin scanchain_bits				
				| scanchain_out_pin scanchain_bits				
				| scanchain_in_pin scanchain_out_pin scanchain_bits;				

scanchain_bits:
				LEFTPAREN BITS INT RIGHTPAREN

groups:
				|
				GROUPS INT SEMI
				groups_list
				END GROUPS;

groups_list:
				| groups_list group;

group:
				MINUS names  
					group_phrases
					SEMI;			

group_phrases:
				| group_phrases PLUS group_phrase;

group_phrase:				
				REGION NAME
				| PROPERTY name_value_list;

end:			END DESIGN;

names:
				name
				| names name;
				
name:
				NAME;

number:
				INT | FLOAT;
				
value:
				name
				| number;
%%

int main () {
	root = new def::Def();

	yyparse ();

	std::cout << "DESIGN " << root->getStringAttribute("design") << std::endl;

	std::vector<def::Pin*>* pins = root->getPinVector();
    std::vector<def::Pin*>::iterator pin_it = pins->begin();
    std::vector<def::Pin*>::iterator pin_end = pins->end();
    while (pin_it != pin_end) {
      	def::Pin* pin  = (*pin_it);
      	std::cout << pin->getName() << " -- " << pin->getNet() << std::endl;
        pin_it++;
    }
	
	
	printf("FINISHED!\n");
}


void yyerror(const char* errstr) {
	printf("YUCK Error: %i, %s, %s\n", line_number, yylval, errstr);
}
